home *** CD-ROM | disk | FTP | other *** search
/ Practical Internet 2002 February / Practical Internet February 2002.iso / pc / Software / Browsing / httrack-3.09e2.exe / {app} / src / htscoremain.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-11-07  |  66.4 KB  |  1,841 lines

  1. /* ------------------------------------------------------------ */
  2. /*
  3. HTTrack Website Copier, Offline Browser for Windows and Unix
  4. Copyright (C) Xavier Roche and other contributors
  5.  
  6. This program is free software; you can redistribute it and/or
  7. modify it under the terms of the GNU General Public License
  8. as published by the Free Software Foundation; either version 2
  9. of the License, or any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  19.  
  20.  
  21. Important notes:
  22.  
  23. - We hereby ask people using this source NOT to use it in purpose of grabbing
  24. emails addresses, or collecting any other private information on persons.
  25. This would disgrace our work, and spoil the many hours we spent on it.
  26.  
  27.  
  28. Please visit our Website: http://www.httrack.com
  29. */
  30.  
  31.  
  32. /* ------------------------------------------------------------ */
  33. /* File: httrack.c subroutines:                                 */
  34. /*       main routine (first called)                            */
  35. /* Author: Xavier Roche                                         */
  36. /* ------------------------------------------------------------ */
  37.  
  38. #include "htscoremain.h"
  39.  
  40. #include "htsglobal.h"
  41. #include "htscore.h"
  42. #include "htsdefines.h"
  43. #include "htsalias.h"
  44. #include "htswrap.h"
  45. #include <ctype.h>
  46. #if HTS_WIN
  47. #else
  48. #ifndef HTS_DO_NOT_USE_UID
  49. /* setuid */
  50. #include <pwd.h>
  51. #include <unistd.h>
  52. #endif
  53. #endif
  54.  
  55. extern int exit_xh;          // sortir prΘmaturΘment
  56.  
  57. // Add a command in the argc/argv
  58. #define cmdl_add(token,argc,argv,buff,ptr) \
  59.   argv[argc]=(buff+ptr); \
  60.   strcpy(argv[argc],token); \
  61.   ptr += (strlen(argv[argc])+2); \
  62.   argc++
  63.  
  64. // Insert a command in the argc/argv
  65. #define cmdl_ins(token,argc,argv,buff,ptr) \
  66.   { \
  67.   int i; \
  68.   for(i=argc;i>0;i--)\
  69.   argv[i]=argv[i-1];\
  70.   } \
  71.   argv[0]=(buff+ptr); \
  72.   strcpy(argv[0],token); \
  73.   ptr += (strlen(argv[0])+2); \
  74.   argc++
  75.  
  76.  
  77. // Main, rΘcupΦre les paramΦtres et appelle le robot
  78. #if HTS_ANALYSTE
  79. int hts_main(int argc, char **argv) {
  80. #else
  81. int main(int argc, char **argv) {
  82. #endif
  83.   char* x_argv[999];      // Patch pour argv et argc: en cas de rΘcupΘration de ligne de commande
  84.   char* x_argvblk=NULL;   // (reprise ou update)
  85.   int   x_ptr=0;          // offset
  86.   /*
  87.   char* x_argv2[999];     // Patch pour config
  88.   char* x_argvblk2=NULL;
  89.   */
  90.   //
  91.   int argv_url=-1;           // ==0 : utiliser cache et doit.log
  92.   char* argv_firsturl=NULL;  // utilisΘ pour nommage par dΘfaut
  93.   char url[65536];         // URLS sΘparΘes par un espace
  94.   // the parametres
  95.   httrackp httrack;
  96.   int httrack_logmode=3;   // ONE log file
  97.   int recuperer=0;       // rΘcupΘrer un plantage (n'arrive jamais, α supprimer)
  98. #if HTS_WIN
  99. #if HTS_ANALYSTE!=2
  100.   WORD   wVersionRequested; /* requested version WinSock API */ 
  101.   WSADATA wsadata;        /* Windows Sockets API data */
  102. #endif
  103. #else
  104. #ifndef HTS_DO_NOT_USE_UID
  105.   int switch_uid=-1,switch_gid=-1;      /* setuid/setgid */
  106. #endif
  107.   int switch_chroot=0;                  /* chroot ? */
  108. #endif
  109.   //
  110.   url[0]='\0';
  111.   //
  112.  
  113. #if HTS_ANALYSTE
  114.   // custom wrappers
  115.   hts_htmlcheck_init         = (t_hts_htmlcheck_init)           htswrap_read("init");
  116.   hts_htmlcheck_uninit       = (t_hts_htmlcheck_uninit)         htswrap_read("free");
  117.   hts_htmlcheck_start        = (t_hts_htmlcheck_start)          htswrap_read("start");
  118.   hts_htmlcheck_end          = (t_hts_htmlcheck_end)            htswrap_read("end");
  119.   hts_htmlcheck_chopt        = (t_hts_htmlcheck_chopt)          htswrap_read("change-options");
  120.   hts_htmlcheck              = (t_hts_htmlcheck)                htswrap_read("check-html");
  121.   hts_htmlcheck_query        = (t_hts_htmlcheck_query)          htswrap_read("query");
  122.   hts_htmlcheck_query2       = (t_hts_htmlcheck_query2)         htswrap_read("query2");
  123.   hts_htmlcheck_query3       = (t_hts_htmlcheck_query3)         htswrap_read("query3");
  124.   hts_htmlcheck_loop         = (t_hts_htmlcheck_loop)           htswrap_read("loop");
  125.   hts_htmlcheck_check        = (t_hts_htmlcheck_check)          htswrap_read("check-link");
  126.   hts_htmlcheck_pause        = (t_hts_htmlcheck_pause)          htswrap_read("pause");
  127.   hts_htmlcheck_filesave     = (t_hts_htmlcheck_filesave)       htswrap_read("save-file");
  128.   hts_htmlcheck_linkdetected = (t_hts_htmlcheck_linkdetected)   htswrap_read("link-detected");
  129.   hts_htmlcheck_xfrstatus    = (t_hts_htmlcheck_xfrstatus)      htswrap_read("transfer-status");
  130. #endif
  131.  
  132.   // options par dΘfaut
  133.   bzero((char *)&httrack, sizeof(httrackp));
  134.   httrack.wizard=2;   // wizard automatique
  135.   httrack.quiet=0;     // questions
  136.   //  
  137.   httrack.travel=0;   // mΩme adresse
  138.   httrack.depth=9999; // mirror total par dΘfaut
  139.   httrack.extdepth=0; // mais pas α l'extΘrieur
  140.   httrack.seeker=1;   // down 
  141.   httrack.urlmode=2;  // relatif par dΘfaut
  142.   httrack.debug=0;    // pas de dΘbug en plus
  143.   httrack.getmode=3;  // linear scan
  144.   httrack.maxsite=-1; // taille max site (aucune)
  145.   httrack.maxfile_nonhtml=-1; // taille max fichier non html
  146.   httrack.maxfile_html=-1;    // idem pour html
  147.   httrack.maxsoc=8;     // nbre socket max
  148.   httrack.fragment=-1;  // pas de fragmentation
  149.   httrack.nearlink=0;   // ne pas prendre les liens non-html "adjacents"
  150.   httrack.makeindex=1;  // faire un index
  151.   httrack.kindex=0;     // index 'keyword'
  152.   httrack.delete_old=1; // effacer anciens fichiers
  153.   httrack.makestat=0;  // pas de fichier de stats
  154.   httrack.maketrack=0; // ni de tracking
  155.   httrack.timeout=120; // timeout par dΘfaut (2 minutes)
  156.   httrack.cache=1;     // cache prioritaire
  157.   httrack.shell=0;     // pas de shell par defaut
  158.   httrack.proxy.active=0;    // pas de proxy
  159.   httrack.user_agent_send=1; // envoyer un user-agent
  160.   strcpy(httrack.user_agent,"Mozilla/4.5 (compatible; HTTrack 3.0x; Windows 98)");
  161.   httrack.savename_83=0;     // noms longs par dΘfaut
  162.   httrack.savename_type=0;   // avec structure originale
  163.   httrack.parsejava=1;       // parser classes
  164.   httrack.hostcontrol=0;     // PAS de control host pour timeout et traffic jammer
  165.   httrack.retry=2;           // 2 retry par dΘfaut
  166.   httrack.errpage=1;         // copier ou gΘnΘrer une page d'erreur en cas d'erreur (404 etc.)
  167.   httrack.check_type=1;      // vΘrifier type si inconnu (cgi,asp..) SAUF / considΘrΘ comme html
  168.   httrack.all_in_cache=0;    // ne pas tout stocker en cache
  169.   httrack.robots=2;          // traiter les robots.txt
  170.   httrack.external=0;        // liens externes normaux
  171.   httrack.passprivacy=0;     // mots de passe dans les fichiers
  172.   httrack.includequery=1;    // include query-string par dΘfaut
  173.   httrack.mirror_first_page=0;  // pas mode mirror links
  174.   httrack.accept_cookie=1;   // gΘrer les cookies
  175.   httrack.cookie=NULL;
  176.   httrack.http10=0;          // laisser http/1.1
  177.   httrack.nocompression=0;   // pas de compression
  178.   httrack.tolerant=0;        // ne pas accepter content-length incorrect
  179.   httrack.parseall=1;        // tout parser (tags inconnus, par exemple)
  180.   httrack.norecatch=0;       // ne pas reprendre les fichiers effacΘs par l'utilisateur
  181.   httrack.verbosedisplay=0;  // pas d'animation texte
  182.   strcpy(httrack.footer,HTS_DEFAULT_FOOTER);
  183.   httrack.ftp_proxy=1;       // proxy http pour ftp
  184.   strcpy(httrack.filelist,"");
  185.   strcpy(httrack.lang_iso,"en, *");
  186.   strcpy(httrack.mimedefs,"\n"); // aucun filtre mime (\n IMPORTANT)
  187.   //
  188.   httrack.log=stdout;
  189.   httrack.errlog=stderr;
  190.   httrack.flush=1;           // flush sur les fichiers log
  191.   httrack.aff_progress=0;
  192.   httrack.keyboard=0;
  193.   //
  194.   strcpy(httrack.path_html,"");
  195.   strcpy(httrack.path_log,"");
  196.   strcpy(httrack.path_bin,"");
  197.   //
  198.   httrack.maxlink=100000;    // 100,000 liens max par dΘfaut (400Kb)
  199.   httrack.maxfilter=500;     // 500 filtres max par dΘfaut (400Kb)
  200.   httrack.maxcache=1048576*32;   // a peu prΦs 32Mo en cache max -- OPTION NON PARAMETRABLE POUR L'INSTANT --
  201.   //httrack.maxcache_anticipate=256;  // maximum de liens α anticiper
  202.   httrack.maxtime=-1;        // temps max en secondes
  203.   httrack.maxrate=-1;        // pas de taux maxi
  204.   httrack.maxconn=10;        // nombre connexions/s
  205.   httrack.waittime=-1;      // wait until.. hh*3600+mm*60+ss
  206.   //
  207.   httrack.exec=argv[0];
  208.   httrack.is_update=0;      // not an update (yet)
  209.   httrack.dir_topindex=0;   // do not built top index (yet)
  210.   //
  211.   httrack.state.stop=0;     // stopper
  212.   //
  213.   _DEBUG_HEAD=0;            // pas de debuggage en tΩtes
  214.   
  215. #if HTS_WIN
  216. #if HTS_ANALYSTE!=2
  217.   {
  218.     int stat;
  219.     wVersionRequested = 0x0101;
  220.     stat = WSAStartup( wVersionRequested, &wsadata );
  221.     if (stat != 0) {
  222.       HTS_PANIC_PRINTF("Winsock not found!\n");
  223.       return -1;
  224.     } else if (LOBYTE(wsadata.wVersion) != 1  && HIBYTE(wsadata.wVersion) != 1) {
  225.       HTS_PANIC_PRINTF("WINSOCK.DLL does not support version 1.1\n");
  226.       WSACleanup();
  227.       return -1;
  228.     }
  229.   }
  230. #endif
  231. #endif
  232.  
  233.   /* Init root dir */
  234.   hts_rootdir(argv[0]);
  235.  
  236. #if HTS_WIN
  237. #else
  238.   /* Terminal is a tty, may ask questions and display funny information */
  239.   if (isatty(1)) {
  240.     httrack.quiet=0;
  241.     httrack.verbosedisplay=1;
  242.   }
  243.   /* Not a tty, no stdin input or funny output! */
  244.   else {
  245.     httrack.quiet=1;
  246.     httrack.verbosedisplay=0;
  247.   }
  248. #endif
  249.  
  250.   /* First test: if -#R then only launch ftp */
  251.   if (argc > 2) {
  252.     if (strcmp(argv[1],"-#R")==0) {
  253.       if (argc==6) {
  254.         lien_back r;
  255.         char* path;
  256.         FILE* fp;
  257.         strcpy(r.url_adr,argv[2]);
  258.         strcpy(r.url_fil,argv[3]);
  259.         strcpy(r.url_sav,argv[4]);
  260.         path=argv[5];
  261.         r.status=1000;
  262.         run_launch_ftp(&r);
  263.         fp=fopen(fconv(path),"wb");
  264.         if (fp) {
  265.           fprintf(fp,"%d %s",r.r.statuscode,r.r.msg);
  266.           fclose(fp); fp=NULL;
  267.           rename(fconv(path),fconcat(path,".ok"));
  268.         } else remove(fconv(path));
  269.       } else {
  270.         printf("htsftp error, wrong parameter number (%d)\n",argc);
  271.       }
  272.       exit(0);   // pas _exit()
  273.     }
  274.   }
  275.  
  276.   // ok, non ftp, continuer
  277.  
  278.  
  279.   // Binary program path?
  280. #ifndef HTS_HTTRACKDIR
  281.   {
  282.     char* path=fslash(argv[0]);
  283.     char* a;
  284.     if ((a=strrchr(path,'/'))) {
  285.       httrack.path_bin[0]='\0';
  286.       strncat(httrack.path_bin,argv[0],(int) a - (int) path);
  287.     }
  288.   }
  289. #else
  290.   strcpy(httrack.path_bin,HTS_HTTRACKDIR);
  291. #endif
  292.  
  293.  
  294.   /* filter CR, LF, TAB.. */
  295.   {
  296.     int na;
  297.     for(na=1;na<argc;na++) {
  298.       char* a;
  299.       while( (a=strchr(argv[na],'\x0d')) ) *a=' ';
  300.       while( (a=strchr(argv[na],'\x0a')) ) *a=' ';
  301.       while( (a=strchr(argv[na],9)) )      *a=' ';
  302.       /* equivalent to "empty parameter" */
  303.       if ((strcmp(argv[na],HTS_NOPARAM)==0) || (strcmp(argv[na],HTS_NOPARAM2)==0))        // (none)
  304.         strcpy(argv[na],"\"\"");
  305.       if (strncmp(argv[na],"-&",2)==0)
  306.         argv[na][1]='%';
  307.     }
  308.   }
  309.  
  310.  
  311.  
  312.   /* create x_argvblk buffer for transformed command line */
  313.   {
  314.     int current_size=0;
  315.     int size;
  316.     int na;
  317.     for(na=0;na<argc;na++)
  318.       current_size += (strlen(argv[na]) + 1);
  319.     if ((size=fsize("config"))>0)
  320.       current_size += size;
  321.     x_argvblk=(char*) malloct(current_size+32768);
  322.     if (x_argvblk == NULL) {
  323.       HTS_PANIC_PRINTF("Error, not enough memory");
  324.       return -1;
  325.     }
  326.     x_argvblk[0]='\0';
  327.     x_ptr=0;
  328.   }
  329.  
  330.   /* Create new argc/argv, replace alias, count URLs, treat -h, -q, -i */
  331.   {
  332.     char _tmp_argv[2][HTS_CDLMAXSIZE];
  333.     char* tmp_argv[2];
  334.     char tmp_error[HTS_CDLMAXSIZE];
  335.     int tmp_argc;
  336.     int x_argc=0;
  337.     int na;
  338.     tmp_argv[0]=_tmp_argv[0];
  339.     tmp_argv[1]=_tmp_argv[1];
  340.     //
  341.     argv_url=0;       /* pour comptage */
  342.     //
  343.     cmdl_add(argv[0],x_argc,x_argv,x_argvblk,x_ptr);
  344.     na=1;             /* commencer aprΦs nom_prg */
  345.     while(na<argc) {
  346.       int result=1;
  347.       tmp_argv[0][0]=tmp_argv[1][0]='\0';
  348.  
  349.       /* VΘrifier argv[] non vide */
  350.       if (strnotempty(argv[na])) {
  351.         
  352.         /* VΘrifier Commande (alias) */
  353.         result=optalias_check(argc,(const char * const *)argv,na,
  354.           &tmp_argc,(char**)tmp_argv,tmp_error);
  355.         if (!result) {
  356.           HTS_PANIC_PRINTF(tmp_error);
  357.           return -1;
  358.         }
  359.         
  360.         /* Copier */
  361.         cmdl_add(tmp_argv[0],x_argc,x_argv,x_argvblk,x_ptr);
  362.         if (tmp_argc > 1) {
  363.           cmdl_add(tmp_argv[1],x_argc,x_argv,x_argvblk,x_ptr);
  364.         }
  365.         
  366.         /* Compter URLs et dΘtecter -i,-q.. */
  367.         if (tmp_argc == 1) {           /* pas -P & co */
  368.           if (!cmdl_opt(tmp_argv[0])) {   /* pas -c0 & co */
  369.             if (argv_url>=0) {
  370.               argv_url++;
  371.               if (!argv_firsturl)
  372.                 argv_firsturl=x_argv[x_argc-1];
  373.             }
  374.           } else {
  375.             if (strcmp(tmp_argv[0],"-h")==0) {
  376.               help(argv[0],!httrack.quiet);
  377.               return 0;
  378.             } else {
  379.               if (strncmp(tmp_argv[0],"--",2)) {   /* pas */
  380.                 if ((strchr(tmp_argv[0],'q')!=NULL))
  381.                   httrack.quiet=1;    // ne pas poser de questions! (nohup par exemple)
  382.                 if ((strchr(tmp_argv[0],'i')!=NULL)) {  // doit.log!
  383.                   argv_url=-1;        /* forcer */
  384.                   httrack.quiet=1;
  385.                 }
  386.               }
  387.             }
  388.           }
  389.         } else if (tmp_argc == 2) {
  390.           if ((strcmp(tmp_argv[0],"-%L")==0)) {  // liste d'URLs
  391.             if (argv_url>=0)
  392.               argv_url++;        /* forcer */
  393.           }
  394.         }
  395.       }
  396.  
  397.       na+=result;
  398.     }
  399.     if (argv_url<0)
  400.       argv_url=0;
  401.  
  402.     /* Nouveaux argc et argv */
  403.     argv=x_argv;
  404.     argc=x_argc;
  405.   }
  406.  
  407.  
  408.  
  409.  
  410.   // Ici on ajoute les arguments de config
  411. /*
  412.   if (fexist("config")) {    // configuration        
  413.     x_argvblk2=(char*) calloct(32768,1);
  414.  
  415.     if (x_argvblk2!=NULL) {
  416.       FILE* fp;
  417.       int x_argc2;
  418.           
  419.       //strcpy(x_argvblk2,"httrack ");
  420.       fp=fopen("config","rb");
  421.       if (fp) {
  422.         linput(fp,x_argvblk2+strlen(x_argvblk2),32000);
  423.         fclose(fp); fp=NULL;
  424.     
  425.         // calculer arguments selon derniers arguments
  426.         x_argv2[0]=argv[0];
  427.         x_argc2=1;
  428.         {
  429.           char* p=x_argvblk2;
  430.           do {
  431.             x_argv2[x_argc2++]=p;
  432.             p=strchr(p,' ');
  433.             if (p) {
  434.               *p=0;    // octet nul (tableau)
  435.               p++;
  436.             }            
  437.           } while(p!=NULL);
  438.         }
  439.         // recopier arguments actuels (pointeurs uniquement)
  440.         {
  441.          int na;
  442.           for(na=1;na<argc;na++) {
  443.             x_argv2[x_argc2++]=argv[na];
  444.           }
  445.         }
  446.         argc=x_argc2;      // nouvel argc
  447.         argv=x_argv2;      // nouvel argv
  448.       }
  449.     }
  450.   }
  451. */
  452.  
  453.  
  454.   // Option O and includerc
  455.   { 
  456.     int loops=0;
  457.     while (loops<2) {
  458.       char* com;
  459.       int na;
  460.       
  461.       for(na=1;na<argc;na++) {
  462.         
  463.         if (argv[na][0]=='"') {
  464.           char tempo[HTS_CDLMAXSIZE];
  465.           strcpy(tempo,argv[na]+1);
  466.           if (tempo[strlen(tempo)-1]!='"') {
  467.             char s[HTS_CDLMAXSIZE];
  468.             sprintf(s,"Missing quote in %s",argv[na]);
  469.             HTS_PANIC_PRINTF(s);
  470.             return -1;
  471.           }
  472.           tempo[strlen(tempo)-1]='\0';
  473.           strcpy(argv[na],tempo);
  474.         }
  475.         
  476.         if (cmdl_opt(argv[na])) { // option
  477.           com=argv[na]+1;
  478.           
  479.           while(*com) {
  480.             switch(*com) {
  481.             case 'O':    // output path
  482.               if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  483.                 HTS_PANIC_PRINTF("Option O needs to be followed by a blank space, and a path (or path,path)");
  484.                 printf("Example: -O /binary/\n");
  485.                 printf("Example: -O /binary/,/log/\n");
  486.                 return -1;
  487.               } else {
  488.                 char* a;
  489.                 na++;
  490.                 strcpy(httrack.path_html,"");
  491.                 strcpy(httrack.path_log,"");
  492.                 a=strstr(argv[na],"\",\"");  // rechercher en premier, au cas ou -O "c:\pipo,test","c:\test"
  493.                 if (!a)
  494.                   a=strchr(argv[na],',');  // 2 path
  495.                 else
  496.                   a++;  // position ,
  497.                 if (a) {
  498.                   strncat(httrack.path_html,argv[na],(int) a-(int) argv[na]);
  499.                   strcat(httrack.path_log,a+1);
  500.                 } else {
  501.                   strcpy(httrack.path_log,argv[na]);
  502.                   strcpy(httrack.path_html,argv[na]);
  503.                 }
  504.                 // Eliminer les cas comme -O "C:\mirror\"
  505.                 if (httrack.path_log[0]=='"') {  // Guillemets
  506.                   char tmp[256];
  507.                   strcpy(tmp,httrack.path_log+1);
  508.                   if (tmp[strlen(tmp)-1]=='"')
  509.                     tmp[strlen(tmp)-1]='\0';
  510.                   strcpy(httrack.path_log,tmp);
  511.                 }
  512.                 if (httrack.path_html[0]=='"') {
  513.                   char tmp[256];
  514.                   strcpy(tmp,httrack.path_html+1);
  515.                   if (tmp[strlen(tmp)-1]=='"')
  516.                     tmp[strlen(tmp)-1]='\0';
  517.                   strcpy(httrack.path_html,tmp);
  518.                 }
  519.                 check_path(httrack.path_log,argv_firsturl);
  520.                 if (check_path(httrack.path_html,argv_firsturl)) {
  521.                   httrack.dir_topindex=1;     // rebuilt top index
  522.                 }
  523.                 
  524.                 //printf("-->%s\n%s\n",httrack.path_html,httrack.path_log);
  525.                 
  526.               }
  527.               break;
  528.             }  // switch
  529.             com++;    
  530.           }  // while
  531.           
  532.         }  // arg
  533.         
  534.       }  // for
  535.      
  536.          /* if doit.log exists, or if new URL(s) defined, 
  537.       then DO NOT load standard config files */
  538.       /* (config files are added in doit.log) */
  539. #if DEBUG_STEPS
  540.       printf("Loading httrackrc/doit.log\n");
  541. #endif
  542.       /* recreate a doit.log (no old doit.log or new URLs (and parameters)) */
  543.       if ((strnotempty(httrack.path_log)) || (strnotempty(httrack.path_html)))
  544.         loops++;      // do not loop once again and do not include rc file (O option exists)
  545.       else {
  546.         if ( (!fexist(fconcat(httrack.path_log,"hts-cache/doit.log"))) || (argv_url>0) ) {
  547.           if (!optinclude_file(fconcat(httrack.path_log,HTS_HTTRACKRC),&argc,argv,x_argvblk,&x_ptr))
  548.             if (!optinclude_file(HTS_HTTRACKRC,&argc,argv,x_argvblk,&x_ptr)) {
  549.               if (!optinclude_file(fconcat(hts_gethome(),"/"HTS_HTTRACKRC),&argc,argv,x_argvblk,&x_ptr)) {
  550. #ifdef HTS_HTTRACKCNF
  551.                 optinclude_file(HTS_HTTRACKCNF,&argc,argv,x_argvblk,&x_ptr);
  552. #endif
  553.               }
  554.             }
  555.         } else
  556.           loops++;      // do not loop once again
  557.       }
  558.  
  559.       loops++;
  560.    } // while
  561.  
  562.   }  // traiter -O
  563.  
  564.  
  565.   
  566.   /* load doit.log and insert in current command line */
  567.   if ( fexist(fconcat(httrack.path_log,"hts-cache/doit.log")) && (argv_url<=0) ) {
  568.     FILE* fp=fopen(fconcat(httrack.path_log,"hts-cache/doit.log"),"rb");
  569.     if (fp) {
  570.       int insert_after=1;     /* insΘrer aprΦs nom au dΘbut */
  571.       //
  572.       char buff[8192];
  573.       char *p,*lastp;
  574.       linput(fp,buff,8000);
  575.       fclose(fp); fp=NULL;
  576.       p=buff;
  577.       do {
  578.         int insert_after_argc;
  579.         // read next
  580.         lastp=p;
  581.         if (p) {
  582.           p=next_token(p,1);
  583.           if (p) {
  584.             *p=0;    // null
  585.             p++;
  586.           }
  587.         }
  588.  
  589.         /* Insert parameters BUT so that they can be in the same order */
  590.         if (lastp) {
  591.           if (strnotempty(lastp)) {
  592.             insert_after_argc=argc-insert_after;
  593.             cmdl_ins(lastp,insert_after_argc,(argv+insert_after),x_argvblk,x_ptr);
  594.             argc=insert_after_argc+insert_after;
  595.             insert_after++;
  596.           }
  597.         }
  598.       } while(lastp!=NULL);
  599.       //fclose(fp);
  600.     }
  601.   }
  602.  
  603.  
  604.   // Existence d'un cache - pas de new mais un old.. renommer
  605. #if DEBUG_STEPS
  606.   printf("Checking cache\n");
  607. #endif
  608.   if ( (!fexist(fconcat(httrack.path_log,"hts-cache/new.dat"))) || (!fexist(fconcat(httrack.path_log,"hts-cache/new.ndx"))) ) {
  609.     if ( (fexist(fconcat(httrack.path_log,"hts-cache/old.dat"))) && (fexist(fconcat(httrack.path_log,"hts-cache/old.ndx"))) ) {
  610.       remove(fconcat(httrack.path_log,"hts-cache/new.dat"));
  611.       remove(fconcat(httrack.path_log,"hts-cache/new.ndx"));
  612.       //remove(fconcat(httrack.path_log,"hts-cache/new.lst"));
  613.       rename(fconcat(httrack.path_log,"hts-cache/old.dat"),fconcat(httrack.path_log,"hts-cache/new.dat"));
  614.       rename(fconcat(httrack.path_log,"hts-cache/old.ndx"),fconcat(httrack.path_log,"hts-cache/new.ndx"));
  615.       //rename(fconcat(httrack.path_log,"hts-cache/old.lst"),fconcat(httrack.path_log,"hts-cache/new.lst"));
  616.     }
  617.   }
  618.  
  619.   /* Interrupted mirror detected */
  620.   if (!httrack.quiet) {
  621.     if (fexist(fconcat(httrack.path_log,"hts-in_progress.lock"))) {
  622.       /* Old cache */
  623.       if ( (fexist(fconcat(httrack.path_log,"hts-cache/old.dat"))) && (fexist(fconcat(httrack.path_log,"hts-cache/old.ndx"))) ) {
  624.         fprintf(httrack.log,"Warning!\n");
  625.         fprintf(httrack.log,"An aborted mirror has been detected!\nThe current temporary cache is required for any update operation and only contains data downloaded during the last aborted session.\nThe former cache might contain more complete information; if you do not want to lose that information, you have to restore it and delete the current cache.\nThis can easily be done here by erasing the hts-cache/new.* files\n");
  626.         fprintf(httrack.log,"Please restart HTTrack with --continue (-iC1) option to override this message!\n");
  627.         exit(0);
  628.       }
  629.     }
  630.   }
  631.     
  632.   // remplacer "macros" comme --spider
  633.   // permet de lancer httrack sans a avoir α se rappeler de syntaxes comme p0C0I0Qc32 ..
  634. #if DEBUG_STEPS
  635.   printf("Checking last macros\n");
  636. #endif
  637.   {
  638.     int i;
  639.     for(i=0;i<argc;i++) {
  640. #if DEBUG_STEPS
  641.       printf("Checking #%d:\n",argv[i]);
  642.       printf("%s\n",argv[i]);
  643. #endif
  644.       if (argv[i][0]=='-') {
  645.         if (argv[i][1]=='-') {  // --xxx
  646.           if ((strfield2(argv[i]+2,"clean")) || (strfield2(argv[i]+2,"tide"))) {  // nettoyer
  647.             strcpy(argv[i]+1,"");
  648.             if (fexist(fconcat(httrack.path_log,"hts-log.txt")))
  649.               remove(fconcat(httrack.path_log,"hts-log.txt"));
  650.             if (fexist(fconcat(httrack.path_log,"hts-err.txt")))
  651.               remove(fconcat(httrack.path_log,"hts-err.txt"));
  652.             if (fexist(fconcat(httrack.path_html,"index.html")))
  653.               remove(fconcat(httrack.path_html,"index.html"));
  654.             if (fexist(fconcat(httrack.path_log,"hts-cache/new.dat")))
  655.               remove(fconcat(httrack.path_log,"hts-cache/new.dat"));
  656.             if (fexist(fconcat(httrack.path_log,"hts-cache/new.ndx")))
  657.               remove(fconcat(httrack.path_log,"hts-cache/new.ndx"));
  658.             if (fexist(fconcat(httrack.path_log,"hts-cache/old.dat")))
  659.               remove(fconcat(httrack.path_log,"hts-cache/old.dat"));
  660.             if (fexist(fconcat(httrack.path_log,"hts-cache/old.ndx")))
  661.               remove(fconcat(httrack.path_log,"hts-cache/old.ndx"));
  662.             if (fexist(fconcat(httrack.path_log,"hts-cache/new.lst")))
  663.               remove(fconcat(httrack.path_log,"hts-cache/new.lst"));
  664.             if (fexist(fconcat(httrack.path_log,"hts-cache/old.lst")))
  665.               remove(fconcat(httrack.path_log,"hts-cache/old.lst"));
  666.             if (fexist(fconcat(httrack.path_log,"hts-cache/doit.log")))
  667.               remove(fconcat(httrack.path_log,"hts-cache/doit.log"));
  668.             if (fexist(fconcat(httrack.path_log,"hts-in_progress.lock")))
  669.               remove(fconcat(httrack.path_log,"hts-in_progress.lock"));
  670.             rmdir(fconcat(httrack.path_log,"hts-cache"));
  671.             //
  672.           } else if (strfield2(argv[i]+2,"catchurl")) {      // capture d'URL via proxy temporaire!
  673.             argv_url=1;     // forcer a passer les parametres
  674.             strcpy(argv[i]+1,"#P");
  675.             //
  676.           } else if (strfield2(argv[i]+2,"updatehttrack")) {
  677. #ifdef _WIN32
  678.             char s[HTS_CDLMAXSIZE];
  679.             sprintf(s,"%s not available in this version",argv[i]);
  680.             HTS_PANIC_PRINTF(s);
  681.             return -1;
  682. #else
  683. #if 0
  684.             char _args[8][256];
  685.             char *args[8];
  686.             
  687.             printf("Cheking for updates...\n");
  688.             strcpy(_args[0],argv[0]);
  689.             strcpy(_args[1],"--get");
  690.             sprintf(_args[2],HTS_UPDATE_WEBSITE,HTS_PLATFORM,"");
  691.             strcpy(_args[3],"--quickinfo");
  692.             args[0]=_args[0];
  693.             args[1]=_args[1];
  694.             args[2]=_args[2];
  695.             args[3]=_args[3];
  696.             args[4]=NULL;
  697.             if (execvp(args[0],args)==-1) {
  698.             }
  699. #endif
  700. #endif
  701.           }
  702.           //
  703.           else {
  704.             char s[HTS_CDLMAXSIZE];
  705.             sprintf(s,"%s not recognized",argv[i]);
  706.             HTS_PANIC_PRINTF(s);
  707.             return -1;
  708.           }
  709.  
  710.         } 
  711.       }
  712.     }
  713.   }
  714.  
  715.   // Compter urls/jokers
  716.   /*
  717.   if (argv_url<=0) { 
  718.     int na;
  719.     argv_url=0;
  720.     for(na=1;na<argc;na++) {
  721.       if ( (strcmp(argv[na],"-P")==0) || (strcmp(argv[na],"-N")==0) || (strcmp(argv[na],"-F")==0) || (strcmp(argv[na],"-O")==0) || (strcmp(argv[na],"-V")==0) ) {
  722.         na++;    // sauter nom de proxy
  723.       } else if (!cmdl_opt(argv[na])) { 
  724.         argv_url++;   // un de plus       
  725.       } else if (strcmp(argv[na],"-h")==0) {
  726.         help(argv[0],!httrack.quiet);
  727.         return 0;
  728.       } else {
  729.         if ((strchr(argv[na],'q')!=NULL))
  730.           httrack.quiet=1;    // ne pas poser de questions! (nohup par exemple)
  731.         if ((strchr(argv[na],'i')!=NULL)) {  // doit.log!
  732.           argv_url=0;
  733.           na=argc;
  734.         }
  735.       }
  736.     }
  737.   }  
  738.   */
  739.  
  740.   // Ici on ajoute les arguments qui ont ΘtΘ appelΘs avant au cas o∙ on rΘcupΦre une session
  741.   // Exemple: httrack www.truc.fr -L0 puis ^C puis httrack sans URL : ajouter URL prΘcΘdente
  742.   /*
  743.   if (argv_url==0) {
  744.     //if ((fexist(fconcat(httrack.path_log,"hts-cache/new.dat"))) && (fexist(fconcat(httrack.path_log,"hts-cache/new.ndx")))) {  // il existe dΘja un cache prΘcΘdent.. renommer
  745.     if (fexist(fconcat(httrack.path_log,"hts-cache/doit.log"))) {    // un cache est prΘsent
  746.       
  747.       x_argvblk=(char*) calloct(32768,1);
  748.       
  749.       if (x_argvblk!=NULL) {
  750.         FILE* fp;
  751.         int x_argc;
  752.         
  753.         //strcpy(x_argvblk,"httrack ");
  754.         fp=fopen(fconcat(httrack.path_log,"hts-cache/doit.log"),"rb");
  755.         if (fp) {
  756.           linput(fp,x_argvblk+strlen(x_argvblk),8192);
  757.           fclose(fp); fp=NULL;
  758.         }
  759.         
  760.         // calculer arguments selon derniers arguments
  761.         x_argv[0]=argv[0];
  762.         x_argc=1;
  763.         {
  764.           char* p=x_argvblk;
  765.           do {
  766.             x_argv[x_argc++]=p;
  767.             //p=strstr(p," ");
  768.             // exemple de chaine: "echo \"test\"" c:\a "\$0"
  769.             p=next_token(p,1);    // prochain token
  770.             if (p) {
  771.               *p=0;    // octet nul (tableau)
  772.               p++;
  773.             }            
  774.           } while(p!=NULL);
  775.         }
  776.         // recopier arguments actuels (pointeurs uniquement)
  777.         {
  778.           int na;
  779.           for(na=1;na<argc;na++) {
  780.             if (strcmp(argv[na],"-O") != 0)    // SAUF le path!
  781.               x_argv[x_argc++]=argv[na];
  782.             else
  783.               na++;
  784.           }
  785.         }
  786.         argc=x_argc;      // nouvel argc
  787.         argv=x_argv;      // nouvel argv
  788.       }
  789.       
  790.       
  791.     }
  792.     //}
  793.   }
  794.   */
  795.   
  796.   // VΘrifier quiet
  797.   /*
  798.   { 
  799.     int na;    
  800.     for(na=1;na<argc;na++) {
  801.       if (!cmdl_opt(argv[na])) { 
  802.         if ((strcmp(argv[na],"-P")==0) || (strcmp(argv[na],"-N")==0) || (strcmp(argv[na],"-F")==0) || (strcmp(argv[na],"-O")==0) || (strcmp(argv[na],"-V")==0))
  803.           na++;    // sauter nom de proxy
  804.       } else {
  805.         if ((strchr(argv[na],'q')!=NULL) || (strchr(argv[na],'i')!=NULL))
  806.           httrack.quiet=1;    // ne pas poser de questions! (nohup par exemple)
  807.       }
  808.     }
  809.   }
  810.   */
  811.  
  812.   // Pas d'URL
  813. #if DEBUG_STEPS
  814.   printf("Checking URLs\n");
  815. #endif
  816.   if (argv_url==0) {
  817.     // PrΘsence d'un cache, que faire?..
  818.     if ((fexist(fconcat(httrack.path_log,"hts-cache/new.dat"))) && (fexist(fconcat(httrack.path_log,"hts-cache/new.ndx")))) {  // il existe dΘja un cache prΘcΘdent.. renommer
  819.       if (fexist(fconcat(httrack.path_log,"hts-cache/doit.log"))) {    // un cache est prΘsent
  820.         if (x_argvblk!=NULL) {
  821.           int m;        
  822.           // Θtablir mode - mode cache: 1 (cache valide) 2 (cache α vΘrifier)
  823.           if (fexist(fconcat(httrack.path_log,"hts-in_progress.lock"))) {    // cache prioritaire
  824.             m=1;
  825.             recuperer=1;
  826.           } else {
  827.             m=2;
  828.           }
  829.           httrack.cache=m;
  830.           
  831.           if (httrack.quiet==0) {  // sinon on continue automatiquement
  832.             HT_REQUEST_START;
  833.             HT_PRINT("A cache (hts-cache/) has been found in the directory ");
  834.             HT_PRINT(httrack.path_log);
  835.             HT_PRINT(LF);
  836.             if (m==1) {
  837.               HT_PRINT("That means that a transfer has been aborted"LF);
  838.               HT_PRINT("OK to Continue ");
  839.             } else {
  840.               HT_PRINT("That means you can update faster the remote site(s)"LF);
  841.               HT_PRINT("OK to Update ");
  842.             }
  843.             HT_PRINT("httrack "); HT_PRINT(x_argvblk); HT_PRINT("?"LF);
  844.             HT_REQUEST_END;
  845.             if (!ask_continue()) return 0;
  846.           }
  847.           
  848.         } else {
  849.           HTS_PANIC_PRINTF("Error, not enough memory");
  850.           return -1;
  851.         }
  852.       } else { // log existe pas
  853.         HTS_PANIC_PRINTF("A cache has been found, but no command line");
  854.         printf("Please launch httrack with proper parameters to reuse the cache\n");
  855.         return -1;
  856.       }
  857.       
  858.     } else {    // aucune URL dΘfinie et pas de cache
  859. #if HTS_ANALYSTE!=2
  860.       if (httrack.quiet) {
  861. #endif
  862.         help(argv[0],!httrack.quiet);
  863.         return -1;
  864. #if HTS_ANALYSTE!=2
  865.       } else {
  866.         help_wizard(&httrack);
  867.         return -1;
  868.       }
  869. #endif
  870.       return 0;
  871.     }
  872.   } else {   // plus de 2 paramΦtres
  873.     // un fichier log existe?
  874.     if (fexist(fconcat(httrack.path_log,"hts-in_progress.lock"))) {  // fichier lock?
  875.       //char s[32];
  876.       
  877.       httrack.cache=1;    // cache prioritaire
  878.       if (httrack.quiet==0) {
  879.         if ((fexist(fconcat(httrack.path_log,"hts-cache/new.dat"))) && (fexist(fconcat(httrack.path_log,"hts-cache/new.ndx")))) {  // il existe dΘja un cache prΘcΘdent.. renommer
  880.           HT_REQUEST_START;
  881.           HT_PRINT("There is a lock-file in the directory ");
  882.           HT_PRINT(httrack.path_log);
  883.           HT_PRINT(LF"That means that a mirror has not been terminated"LF);
  884.           HT_PRINT("Be sure you call httrack with proper parameters"LF);
  885.           HT_PRINT("(The cache allows you to restart faster the transfer)"LF);
  886.           HT_REQUEST_END;
  887.           if (!ask_continue()) return 0;
  888.         }
  889.       }
  890.     } else if (fexist(fconcat(httrack.path_html,"index.html"))) {
  891.       //char s[32];
  892.       httrack.cache=2;  // cache vient aprΦs test de validitΘ
  893.       if (httrack.quiet==0) {
  894.         if ((fexist(fconcat(httrack.path_log,"hts-cache/new.dat"))) && (fexist(fconcat(httrack.path_log,"hts-cache/new.ndx")))) {  // il existe dΘja un cache prΘcΘdent.. renommer
  895.           HT_REQUEST_START;
  896.           HT_PRINT("There is an index.html and a hts-cache folder in the directory ");
  897.           HT_PRINT(httrack.path_log);
  898.           HT_PRINT(LF"A site may have been mirrored here, that could mean that you want to update it"LF);
  899.           HT_PRINT("Be sure parameters are ok"LF);
  900.           HT_REQUEST_END;
  901.           if (!ask_continue()) return 0;
  902.         } else {
  903.           HT_REQUEST_START;
  904.           HT_PRINT("There is an index.html in the directory ");
  905.           HT_PRINT(httrack.path_log);
  906.           HT_PRINT(" but no cache"LF);
  907.           HT_PRINT("There is an index.html in the directory, but no cache"LF);
  908.           HT_PRINT("A site may have been mirrored here, and erased.."LF);
  909.           HT_PRINT("Be sure parameters are ok"LF);
  910.           HT_REQUEST_END;
  911.           if (!ask_continue()) return 0;
  912.         }
  913.       }
  914.     }
  915.   }
  916.   
  917.   
  918.   // Treat parameters
  919.   // Traiter les paramΦtres
  920. #if DEBUG_STEPS
  921.   printf("Analyze parameters\n");
  922. #endif
  923.   { 
  924.     char* com;
  925.     int na;
  926.     
  927.     for(na=1;na<argc;na++) {
  928.  
  929.       if (argv[na][0]=='"') {
  930.         char tempo[HTS_CDLMAXSIZE];
  931.         strcpy(tempo,argv[na]+1);
  932.         if (tempo[strlen(tempo)-1]!='"') {
  933.           char s[HTS_CDLMAXSIZE];
  934.           sprintf(s,"Missing quote in %s",argv[na]);
  935.           HTS_PANIC_PRINTF(s);
  936.           return -1;
  937.         }
  938.         tempo[strlen(tempo)-1]='\0';
  939.         strcpy(argv[na],tempo);
  940.       }
  941.  
  942.       if (cmdl_opt(argv[na])) { // option
  943.         com=argv[na]+1;
  944.         
  945.         while(*com) {
  946.           switch(*com) {
  947.           case ' ': case 9: case '-': case '\0': break;
  948.             //
  949.           case 'h': help(argv[0],0); return 0;   // dΘja fait normalement
  950.             //
  951.           case 'g':    // rΘcupΘrer un (ou plusieurs) fichiers isolΘs
  952.             httrack.wizard=2;             // le wizard on peut plus s'en passer..
  953.             //httrack.wizard=0;             // pas de wizard
  954.             httrack.cache=0;              // ni de cache
  955.             httrack.makeindex=0;          // ni d'index
  956.             httrack_logmode=1;            // erreurs α l'Θcran
  957.             httrack.savename_type=1003;   // mettre dans le rΘpertoire courant
  958.             httrack.depth=0;              // ne pas explorer la page
  959.             httrack.accept_cookie=0;      // pas de cookies
  960.             break;
  961.           case 'w': httrack.wizard=2;    // wizard 'soft' (ne pose pas de questions)
  962.             httrack.travel=0;
  963.             httrack.seeker=1;
  964.             break;
  965.           case 'W': httrack.wizard=1;    // Wizard-Help (pose des questions)
  966.             httrack.travel=0;
  967.             httrack.seeker=1;
  968.             break;
  969.           case 'r':                      // n'est plus le recurse get bestial mais wizard itou!
  970.             if (isdigit((unsigned char)*(com+1))) {
  971.               sscanf(com+1,"%d",&httrack.depth);
  972.               while(isdigit((unsigned char)*(com+1))) com++;
  973.             } else httrack.depth=3;
  974.             break;
  975. /*
  976.           case 'r': httrack.wizard=0;
  977.             if (isdigit((unsigned char)*(com+1))) {
  978.               sscanf(com+1,"%d",&httrack.depth);
  979.               while(isdigit((unsigned char)*(com+1))) com++;
  980.             } else httrack.depth=3;
  981.             break;
  982. */
  983.             //
  984.             // note: les tests httrack.depth sont pour Θviter de faire
  985.             // un miroir du web (:-O) accidentelement ;-)
  986.           case 'a': /*if (httrack.depth==9999) httrack.depth=3;*/
  987.             httrack.travel=0+(httrack.travel&256); break;
  988.           case 'd': /*if (httrack.depth==9999) httrack.depth=3;*/
  989.             httrack.travel=1+(httrack.travel&256); break;
  990.           case 'l': /*if (httrack.depth==9999) httrack.depth=3;*/
  991.             httrack.travel=2+(httrack.travel&256); break;
  992.           case 'e': /*if (httrack.depth==9999) httrack.depth=3;*/
  993.             httrack.travel=7+(httrack.travel&256); break;
  994.           case 't': httrack.travel|=256; break;
  995.           case 'n': httrack.nearlink=1; break;
  996.           case 'x': httrack.external=1; break;
  997.             //
  998.           case 'U': httrack.seeker=2; break;
  999.           case 'D': httrack.seeker=1; break;
  1000.           case 'S': httrack.seeker=0; break;
  1001.           case 'B': httrack.seeker=3; break;
  1002.             //
  1003.           case 'Y': httrack.mirror_first_page=1; break;
  1004.             //
  1005.           case 'q': case 'i': httrack.quiet=1; break;
  1006.             //
  1007.           case 'Q': httrack_logmode=0; break;
  1008.           case 'v': httrack_logmode=1; break;
  1009.           case 'f': httrack_logmode=2; if (*(com+1)=='2') httrack_logmode=3; while(isdigit((unsigned char)*(com+1))) com++; break;
  1010.             //
  1011.           //case 'A': httrack.urlmode=1; break;
  1012.           //case 'R': httrack.urlmode=2; break;
  1013.           case 'K': httrack.urlmode=0; 
  1014.             if (isdigit((unsigned char)*(com+1))) {
  1015.               sscanf(com+1,"%d",&httrack.urlmode);
  1016.               if (httrack.urlmode == 0) {  // in fact K0 ==> K2
  1017.                                            // and K ==> K0
  1018.                 httrack.urlmode=2;
  1019.               }
  1020.               while(isdigit((unsigned char)*(com+1))) com++; 
  1021.             }
  1022.             //if (*(com+1)=='0') { httrack.urlmode=2; com++; } break;
  1023.             //
  1024.           case 'c':
  1025.             if (isdigit((unsigned char)*(com+1))) {
  1026.               sscanf(com+1,"%d",&httrack.maxsoc);
  1027.               while(isdigit((unsigned char)*(com+1))) com++;
  1028.               httrack.maxsoc=max(httrack.maxsoc,1);     // FORCER A 1
  1029.             } else httrack.maxsoc=8;
  1030.             
  1031.             break;
  1032.             //
  1033.           case 'p': sscanf(com+1,"%d",&httrack.getmode); while(isdigit((unsigned char)*(com+1))) com++; break;
  1034.             //        
  1035.           case 'G': sscanf(com+1,"%d",&httrack.fragment); while(isdigit((unsigned char)*(com+1))) com++; break;
  1036.           case 'M': sscanf(com+1,"%d",&httrack.maxsite); while(isdigit((unsigned char)*(com+1))) com++; break;
  1037.           case 'm': sscanf(com+1,"%d",&httrack.maxfile_nonhtml); while(isdigit((unsigned char)*(com+1))) com++; 
  1038.             if (*(com+1)==',') {
  1039.               com++;
  1040.               sscanf(com+1,"%d",&httrack.maxfile_html); while(isdigit((unsigned char)*(com+1))) com++;
  1041.             } else httrack.maxfile_html=-1;
  1042.             break;
  1043.             //
  1044.           case 'T': sscanf(com+1,"%d",&httrack.timeout); while(isdigit((unsigned char)*(com+1))) com++; break;
  1045.           case 'J': sscanf(com+1,"%d",&httrack.rateout); while(isdigit((unsigned char)*(com+1))) com++; break;
  1046.           case 'R': sscanf(com+1,"%d",&httrack.retry); while(isdigit((unsigned char)*(com+1))) com++; break;
  1047.           case 'E': sscanf(com+1,"%d",&httrack.maxtime); while(isdigit((unsigned char)*(com+1))) com++; break;
  1048.           case 'H': sscanf(com+1,"%d",&httrack.hostcontrol); while(isdigit((unsigned char)*(com+1))) com++; break;
  1049.           case 'A': sscanf(com+1,"%d",&httrack.maxrate); while(isdigit((unsigned char)*(com+1))) com++; break;
  1050.  
  1051.           case 'j': httrack.parsejava=1; if (*(com+1)=='0') { httrack.parsejava=0; com++; } break;
  1052.             //
  1053.           case 'I': httrack.makeindex=1; if (*(com+1)=='0') { httrack.makeindex=0; com++; } break;
  1054.             //
  1055.           case 'X': httrack.delete_old=1; if (*(com+1)=='0') { httrack.delete_old=0; com++; } break;
  1056.             //
  1057.           case 'b': sscanf(com+1,"%d",&httrack.accept_cookie); while(isdigit((unsigned char)*(com+1))) com++; break;
  1058.             //
  1059.           case 'N':
  1060.             if (strcmp(argv[na],"-N")==0) {    // Tout seul
  1061.               if ((na+1>=argc) || (argv[na+1][0]=='-')) {  // erreur
  1062.                 HTS_PANIC_PRINTF("Option N needs a number, or needs to be followed by a blank space, and a string");
  1063.                 printf("Example: -N4\n");
  1064.                 return -1;
  1065.               } else {
  1066.                 na++;
  1067.                 if (strlen(argv[na])>=127) {
  1068.                   HTS_PANIC_PRINTF("Userdef structure string too long");
  1069.                   return -1;
  1070.                 }
  1071.                 strcpy(httrack.savename_userdef,argv[na]);
  1072.                 if (strnotempty(httrack.savename_userdef))
  1073.                   httrack.savename_type = -1;    // userdef!
  1074.                 else
  1075.                   httrack.savename_type = 0;    // -N "" : par dΘfaut
  1076.               }
  1077.             } else {
  1078.               sscanf(com+1,"%d",&httrack.savename_type); while(isdigit((unsigned char)*(com+1))) com++;
  1079.             }
  1080.             break;
  1081.           case 'L': sscanf(com+1,"%d",&httrack.savename_83); httrack.savename_83=!httrack.savename_83; while(isdigit((unsigned char)*(com+1))) com++; break;
  1082.           case 's': 
  1083.             if (isdigit((unsigned char)*(com+1))) {
  1084.               sscanf(com+1,"%d",&httrack.robots);
  1085.               while(isdigit((unsigned char)*(com+1))) com++;
  1086.             } else httrack.robots=1;
  1087. #if DEBUG_ROBOTS
  1088.             printf("robots.txt mode set to %d\n",httrack.robots);
  1089. #endif
  1090.             break;
  1091.           case 'o': sscanf(com+1,"%d",&httrack.errpage); while(isdigit((unsigned char)*(com+1))) com++; break;
  1092.           case 'u': sscanf(com+1,"%d",&httrack.check_type); while(isdigit((unsigned char)*(com+1))) com++; break;
  1093.             //
  1094.           case 'C': 
  1095.             if (isdigit((unsigned char)*(com+1))) {
  1096.               sscanf(com+1,"%d",&httrack.cache);
  1097.               while(isdigit((unsigned char)*(com+1))) com++;
  1098.             } else httrack.cache=1;
  1099.             break;
  1100.           case 'k': httrack.all_in_cache=1; break;
  1101.             //
  1102.           case 'z': httrack.debug=1; break;  // petit debug
  1103.           case 'Z': httrack.debug=2; break;  // GROS debug
  1104.             //
  1105.           case '&': case '%': {    // deuxiΦme jeu d'options
  1106.             com++;
  1107.             switch(*com) {
  1108.             case 'x': httrack.passprivacy=1; if (*(com+1)=='0') { httrack.passprivacy=0; com++; } break;   // No passwords in html files
  1109.             case 'q': httrack.includequery=1; if (*(com+1)=='0') { httrack.includequery=0; com++; } break;   // No passwords in html files
  1110.             case 'I': httrack.kindex=1; if (*(com+1)=='0') { httrack.kindex=0; com++; } break;   // Keyword Index
  1111.             case 'c': sscanf(com+1,"%d",&httrack.maxconn); while(isdigit((unsigned char)*(com+1))) com++; break;
  1112.             case 'e': sscanf(com+1,"%d",&httrack.extdepth); while(isdigit((unsigned char)*(com+1))) com++; break;
  1113.             case 'B': httrack.tolerant=1; if (*(com+1)=='0') { httrack.tolerant=0; com++; } break;   // HTTP/1.0 notamment
  1114.             case 'h': httrack.http10=1; if (*(com+1)=='0') { httrack.http10=0; com++; } break;   // HTTP/1.0
  1115.             case 'z': httrack.nocompression=1; if (*(com+1)=='0') { httrack.nocompression=0; com++; } break;   // pas de compression
  1116.             case 'f': httrack.ftp_proxy=1; if (*(com+1)=='0') { httrack.ftp_proxy=0; com++; } break;   // proxy http pour ftp
  1117.             case 'P': httrack.parseall=1; if (*(com+1)=='0') { httrack.parseall=0; com++; } break;   // tout parser
  1118.             case 'n': httrack.norecatch=1; if (*(com+1)=='0') { httrack.norecatch=0; com++; } break;   // ne pas reprendre fichiers effacΘs localement
  1119.             case 's': httrack.sizehack=1; if (*(com+1)=='0') { httrack.sizehack=0; com++; } break;   // hack sur content-length
  1120.             case 'v': httrack.verbosedisplay=2; if (isdigit((unsigned char)*(com+1))) { sscanf(com+1,"%d",&httrack.verbosedisplay); while(isdigit((unsigned char)*(com+1))) com++; } break;
  1121.             case 'L':    // URL list
  1122.               if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  1123.                 HTS_PANIC_PRINTF("Option %L needs to be followed by a blank space, and a text filename");
  1124.                 printf("Example: -%%L \"mylist.txt\"\n");
  1125.                 return -1;
  1126.               } else{
  1127.                 na++;
  1128.                 if (strlen(argv[na])>=254) {
  1129.                   HTS_PANIC_PRINTF("File list string too long");
  1130.                   return -1;
  1131.                 }
  1132.                 strcpy(httrack.filelist,argv[na]);
  1133.               }
  1134.               break;
  1135.             case 'A':    // assume
  1136.               if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  1137.                 HTS_PANIC_PRINTF("Option %A needs to be followed by a blank space, and a filesystemtype=mimetype/mimesubtype parameters");
  1138.                 printf("Example: -%%A php3=text/html,asp=text/html\n");
  1139.                 return -1;
  1140.               } else{
  1141.                 char* a;
  1142.                 na++;
  1143.                 if ( (strlen(argv[na]) + strlen(httrack.mimedefs) + 4) >= sizeof(httrack.mimedefs)) {
  1144.                   HTS_PANIC_PRINTF("Mime definition string too long");
  1145.                   return -1;
  1146.                 }
  1147.                 // --assume standard
  1148.                 if (strcmp(argv[na],"standard") == 0) {
  1149.                   strcpy(httrack.mimedefs,"\n");
  1150.                   strcat(httrack.mimedefs,HTS_ASSUME_STANDARD);
  1151.                   strcat(httrack.mimedefs,"\n");
  1152.                 } else {
  1153.                   strcat(httrack.mimedefs,argv[na]);
  1154.                   strcat(httrack.mimedefs,"\n");
  1155.                 }
  1156.                 a=httrack.mimedefs;
  1157.                 while(*a) {
  1158.                   switch(*a) {
  1159.                   case ',': case ' ': case '\r': case ';': case '\t':
  1160.                     *a='\n';
  1161.                     break;
  1162.                   }
  1163.                   a++;
  1164.                 }
  1165.               }
  1166.               break;
  1167.               //
  1168.             case 'l': 
  1169.               if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  1170.                 HTS_PANIC_PRINTF("Option %l needs to be followed by a blank space, and an ISO language code");
  1171.                 printf("Example: -%%l \"en\"\n");
  1172.                 return -1;
  1173.               } else{
  1174.                 na++;
  1175.                 if (strlen(argv[na])>=62) {
  1176.                   HTS_PANIC_PRINTF("Lang list string too long");
  1177.                   return -1;
  1178.                 }
  1179.                 strcpy(httrack.lang_iso,argv[na]);
  1180.               }
  1181.               break;
  1182.               //
  1183.             case 'F':     // footer id
  1184.               if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  1185.                 HTS_PANIC_PRINTF("Option %F needs to be followed by a blank space, and a footer string");
  1186.                 printf("Example: -%%F \"<!-- Mirrored from %%s by HTTrack Website Copier/"HTTRACK_AFF_VERSION" "HTTRACK_AFF_AUTHORS", %%s -->\"\n");
  1187.                 return -1;
  1188.               } else{
  1189.                 na++;
  1190.                 if (strlen(argv[na])>=254) {
  1191.                   HTS_PANIC_PRINTF("Footer string too long");
  1192.                   return -1;
  1193.                 }
  1194.                 strcpy(httrack.footer,argv[na]);
  1195.               }
  1196.               break;
  1197.             case 'H':                 // debug headers
  1198.               _DEBUG_HEAD=1;
  1199.               break;
  1200.             case 'O':
  1201. #if HTS_WIN
  1202.               printf("Warning option -%%O has no effect in this system (chroot)\n");
  1203. #else
  1204.               switch_chroot=1;
  1205. #endif
  1206.               break;
  1207.             case 'U':                 // setuid
  1208.               if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  1209.                 HTS_PANIC_PRINTF("Option %U needs to be followed by a blank space, and a username");
  1210.                 printf("Example: -%%U smith\n");
  1211.                 return -1;
  1212.               } else {
  1213.                 na++;
  1214. #if HTS_WIN
  1215.                 printf("Warning option -%%U has no effect on this system (setuid)\n");
  1216. #else
  1217. #ifndef HTS_DO_NOT_USE_UID
  1218.                 /* Change the user id and gid */
  1219.                 {
  1220.                   struct passwd* userdef=getpwnam((const char*)argv[na]);
  1221.                   if (userdef) {    /* we'll have to switch the user id */
  1222.                     switch_gid=userdef->pw_gid;
  1223.                     switch_uid=userdef->pw_uid;
  1224.                   }
  1225.                 }
  1226. #else
  1227.                 printf("Warning option -%%U has no effect with this compiled version (setuid)\n");
  1228. #endif
  1229. #endif
  1230.               }
  1231.               break;
  1232.             }
  1233.                     }
  1234.             break;
  1235.             //
  1236.           case '#':  { // non documentΘ (appel de l'interface)
  1237.             com++;
  1238.             switch(*com) {
  1239.             case 'f': httrack.flush=1; break;
  1240.             case 'h':
  1241.               printf("HTTrack version "HTTRACK_VERSION"\n");
  1242.               exit(1);
  1243.               break;
  1244.             case 'p': httrack.aff_progress=1; break;
  1245.             case 'S': httrack.shell=1; break;  // stdin sur un shell
  1246.             case 'K': httrack.keyboard=1; break;  // vΘrifier stdin
  1247.               //
  1248.             case 'L': sscanf(com+1,"%d",&httrack.maxlink); while(isdigit((unsigned char)*(com+1))) com++; break;
  1249.             case 'F': sscanf(com+1,"%d",&httrack.maxfilter); while(isdigit((unsigned char)*(com+1))) com++; break;
  1250.             case 'Z': httrack.makestat=1; break;
  1251.             case 'T': httrack.maketrack=1; break;
  1252.             case 'u': sscanf(com+1,"%d",&httrack.waittime); while(isdigit((unsigned char)*(com+1))) com++; break;
  1253.               
  1254.             case 'R':    // ohh ftp, catch->ftpget
  1255.               HTS_PANIC_PRINTF("Unexpected internal error with -#R command");
  1256.               return -1;        
  1257.               break;
  1258.             case 'P': {     // catchurl
  1259.               help_catchurl(httrack.path_log);
  1260.               return 0;
  1261.                       }
  1262.               break;
  1263.           
  1264.             case '0':   /* test #0 : filters */
  1265.               if (na+2>=argc) {
  1266.                 HTS_PANIC_PRINTF("Option #0 needs to be followed by a filter string and a string");
  1267.                 printf("Example: '-#0' '*.gif' 'foo.gif'\n");
  1268.                 return -1;
  1269.               } else {
  1270.                 if (strjoker(argv[na+2],argv[na+1],NULL,NULL))
  1271.                   printf("%s does match %s\n",argv[na+2],argv[na+1]);
  1272.                 else
  1273.                   printf("%s does NOT match %s\n",argv[na+2],argv[na+1]);
  1274.                 return 0;
  1275.               }
  1276.               break;
  1277.             case '!':
  1278.               if (na+1>=argc) {
  1279.                 HTS_PANIC_PRINTF("Option #! needs to be followed by a commandline");
  1280.                 printf("Example: '-#!' 'echo hello'\n");
  1281.                 return -1;
  1282.               } else {
  1283.                 system(argv[na+1]);
  1284.               }
  1285.               break;
  1286.  
  1287.             default: printf("Internal option %c not recognized\n",*com); break;
  1288.             }
  1289.                      }
  1290.             break; 
  1291.           case 'O':    // output path
  1292.             na++;     // sauter, dΘja traitΘ
  1293.             break;
  1294.           case 'P':    // proxy
  1295.             if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  1296.               HTS_PANIC_PRINTF("Option P needs to be followed by a blank space, and a proxy proxy:port or user:id@proxy:port");
  1297.               printf("Example: -P proxy.myhost.com:8080\n");
  1298.               return -1;
  1299.             } else {
  1300.               char* a;
  1301.               na++;
  1302.               httrack.proxy.active=1;
  1303.               // Rechercher MAIS en partant de la fin α cause de user:pass@proxy:port
  1304.               a = argv[na] + strlen(argv[na]) -1;
  1305.               // a=strstr(argv[na],":");  // port
  1306.               while( ((int) a > (int) argv[na]) && (*a != ':') && (*a != '@') ) a--;
  1307.               if (*a == ':') {  // un port est prΘsent, <proxy>:port
  1308.                 sscanf(a+1,"%d",&httrack.proxy.port);
  1309.                 httrack.proxy.name[0]='\0';
  1310.                 strncat(httrack.proxy.name,argv[na],(int) a-(int) argv[na]);
  1311.               } else {  // <proxy>
  1312.                 httrack.proxy.port=8080;
  1313.                 strcpy(httrack.proxy.name,argv[na]);
  1314.               }
  1315.             }
  1316.             break;
  1317.           case 'F':    // user-agent field
  1318.             if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  1319.               HTS_PANIC_PRINTF("Option F needs to be followed by a blank space, and a user-agent name");
  1320.               printf("Example: -F \"my_user_agent/1.0\"\n");
  1321.               return -1;
  1322.             } else{
  1323.               na++;
  1324.               if (strlen(argv[na])>=126) {
  1325.                 HTS_PANIC_PRINTF("User-agent length too long");
  1326.                 return -1;
  1327.               }
  1328.               strcpy(httrack.user_agent,argv[na]);
  1329.               if (strnotempty(httrack.user_agent))
  1330.                 httrack.user_agent_send=1;
  1331.               else
  1332.                 httrack.user_agent_send=0;    // -F "" dΘsactive l'option
  1333.             }
  1334.             break;
  1335.             //
  1336.           case 'V':    // execute command
  1337.             if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  1338.               HTS_PANIC_PRINTF("Option V needs to be followed by a system-command string");
  1339.               printf("Example: -V \"tar uvf some.tar \\$0\"\n");
  1340.               return -1;
  1341.             } else{
  1342.               na++;
  1343.               if (strlen(argv[na])>=2048) {
  1344.                 HTS_PANIC_PRINTF("System-command length too long");
  1345.                 return -1;
  1346.               }
  1347.               strcpy(httrack.sys_com,argv[na]);
  1348.               if (strnotempty(httrack.sys_com))
  1349.                 httrack.sys_com_exec=1;
  1350.               else
  1351.                 httrack.sys_com_exec=0;    // -V "" dΘsactive l'option
  1352.             }
  1353.             break;
  1354.             //
  1355.           default: {
  1356.             char s[HTS_CDLMAXSIZE];
  1357.             sprintf(s,"invalid option %c\n",*com);
  1358.             HTS_PANIC_PRINTF(s);
  1359.             return -1;
  1360.                    }
  1361.             break;
  1362.           }  // switch
  1363.           com++;    
  1364.         }  // while
  1365.         
  1366.       }  else {  // URL/filters
  1367.         char tempo[1024];       
  1368.         if (strnotempty(url)) strcat(url," ");  // espace de sΘparation
  1369.         strcpy(tempo,unescape_http_unharm(argv[na]));
  1370.         escape_spc_url(tempo);
  1371.         strcat(url,tempo);
  1372.       }  // if argv=- etc. 
  1373.       
  1374.     }  // for
  1375.   }
  1376.   
  1377. #if BDEBUG==3  
  1378.   printf("URLs/filters=%s\n",url);
  1379. #endif
  1380.  
  1381. #if DEBUG_STEPS
  1382.   printf("Analyzing parameters done\n");
  1383. #endif
  1384.  
  1385.  
  1386. #if HTS_WIN
  1387. #else
  1388. #ifndef HTS_DO_NOT_USE_UID
  1389.   /* Chroot - xxc */
  1390.   if (switch_chroot) {
  1391.     uid_t userid=getuid();
  1392.     //struct passwd* userdef=getpwuid(userid);
  1393.     //if (userdef) {
  1394.     if (!userid) {
  1395.       //if (strcmp(userdef->pw_name,"root")==0) {
  1396.       char rpath[1024];
  1397.       //printf("html=%s log=%s\n",httrack.path_html,httrack.path_log);    // xxc
  1398.       if ((httrack.path_html[0]) && (httrack.path_log[0])) {
  1399.         char *a=httrack.path_html,*b=httrack.path_log,*c=NULL,*d=NULL;
  1400.         c=a; d=b;
  1401.         while ((*a) && (*a == *b)) {
  1402.           if (*a=='/') { c=a; d=b; }
  1403.           a++;
  1404.           b++;
  1405.         }
  1406.  
  1407.         rpath[0]='\0';
  1408.         if (c != httrack.path_html) {
  1409.           if (httrack.path_html[0]!='/')
  1410.             strcat(rpath,"./");
  1411.           strncat(rpath,httrack.path_html,(int) c - (int) httrack.path_html);
  1412.         }
  1413.         {
  1414.           char tmp[1024];
  1415.           strcpy(tmp,c); strcpy(httrack.path_html,tmp);
  1416.           strcpy(tmp,d); strcpy(httrack.path_log,tmp);
  1417.         }
  1418.       } else {
  1419.         strcpy(rpath,"./");
  1420.         strcpy(httrack.path_html,"/");
  1421.         strcpy(httrack.path_log,"/");
  1422.       }
  1423.       if (rpath[0]) {
  1424.         printf("[changing root path to %s (path_data=%s,path_log=%s)]\n",rpath,httrack.path_html,httrack.path_log);
  1425.         if (chroot(rpath)) {
  1426.           printf("ERROR! Can not chroot to %s!\n",rpath);
  1427.           exit(0);
  1428.         }
  1429.         if (chdir("/")) {     /* new root */
  1430.           printf("ERROR! Can not chdir to %s!\n",rpath);
  1431.           exit(0);
  1432.         }
  1433.       } else
  1434.         printf("WARNING: chroot not possible with these paths\n");
  1435.     }
  1436.     //}
  1437.   }
  1438.  
  1439.   /* Setuid */
  1440.   if (switch_uid>=0) {
  1441.     printf("[setting user/group to %d/%d]\n",switch_uid,switch_gid);
  1442.     if (setgid(switch_gid))
  1443.       printf("WARNING! Can not setgid to %d!\n",switch_gid);
  1444.     if (setuid(switch_uid))
  1445.       printf("WARNING! Can not setuid to %d!\n",switch_uid);
  1446.   }
  1447.  
  1448.   /* Final check */
  1449.   {
  1450.     uid_t userid=getuid();
  1451.     if (!userid) {              /* running as r00t */
  1452.       printf("WARNING! You are running this program as root!\n");
  1453.       printf("It might be a good idea to use the -%%U option to change the userid:\n");
  1454.       printf("Example: -%%U smith\n\n");
  1455.     }
  1456.   }
  1457. #endif
  1458. #endif
  1459.   
  1460.   //printf("WARNING! This is *only* a beta-release of HTTrack\n");
  1461.   io_flush;
  1462.   
  1463. #if DEBUG_STEPS
  1464.   printf("Cache & log settings\n");
  1465. #endif
  1466.   
  1467.   // on utilise le cache..
  1468.   // en cas de prΘsence des deux versions, garder la version la plus avancΘe,
  1469.   // cad la version contenant le plus de fichiers  
  1470.   if (httrack.cache) {
  1471.     if (fexist(fconcat(httrack.path_log,"hts-in_progress.lock"))) {   // problemes..
  1472.       if (fexist(fconcat(httrack.path_log,"hts-cache/new.dat")) && fexist(fconcat(httrack.path_log,"hts-cache/new.ndx"))) { 
  1473.         if (fexist(fconcat(httrack.path_log,"hts-cache/old.dat")) && fexist(fconcat(httrack.path_log,"hts-cache/old.ndx"))) {
  1474.           // switcher si new<32Ko et old>65Ko (tailles arbitraires) ?
  1475.           // ce cas est peut Ωtre une erreur ou un crash d'un miroir ancien, prendre
  1476.           // alors l'ancien cache
  1477.           if (fsize(fconcat(httrack.path_log,"hts-cache/new.dat"))<32768) {
  1478.             if (fsize(fconcat(httrack.path_log,"hts-cache/old.dat"))>65536) {
  1479.               if (fsize(fconcat(httrack.path_log,"hts-cache/old.dat")) > fsize(fconcat(httrack.path_log,"hts-cache/new.dat"))) {
  1480.                 remove(fconcat(httrack.path_log,"hts-cache/new.dat"));
  1481.                 remove(fconcat(httrack.path_log,"hts-cache/new.ndx"));
  1482.                 rename(fconcat(httrack.path_log,"hts-cache/old.dat"),fconcat(httrack.path_log,"hts-cache/new.dat"));
  1483.                 rename(fconcat(httrack.path_log,"hts-cache/old.ndx"),fconcat(httrack.path_log,"hts-cache/new.ndx"));  
  1484.                 //} else {  // ne rien faire
  1485.                 //  remove("hts-cache/old.dat");
  1486.                 //  remove("hts-cache/old.ndx");
  1487.               }
  1488.             }
  1489.           }
  1490.         }
  1491.       }
  1492.     }
  1493.   }
  1494.  
  1495.   // DΘbuggage des en tΩtes
  1496.   if (_DEBUG_HEAD) {
  1497.     ioinfo=fopen(fconcat(httrack.path_log,"hts-ioinfo.txt"),"wb");
  1498.   }
  1499.   
  1500.   {
  1501.     char n_lock[256];
  1502.     // on peut pas avoir un affichage ET un fichier log
  1503.     // ca sera pour la version 2
  1504.     if (httrack_logmode==1) {
  1505.       httrack.log=stdout;
  1506.       httrack.errlog=stderr;
  1507.     } else if (httrack_logmode>=2) {
  1508.       // deux fichiers log
  1509.       structcheck(httrack.path_log);
  1510.       if (fexist(fconcat(httrack.path_log,"hts-log.txt")))
  1511.         remove(fconcat(httrack.path_log,"hts-log.txt"));
  1512.       if (fexist(fconcat(httrack.path_log,"hts-err.txt")))
  1513.         remove(fconcat(httrack.path_log,"hts-err.txt"));
  1514.  
  1515.       httrack.log=fopen(fconcat(httrack.path_log,"hts-log.txt"),"w");
  1516.       if (httrack_logmode==2)
  1517.         httrack.errlog=fopen(fconcat(httrack.path_log,"hts-err.txt"),"w");
  1518.       else
  1519.         httrack.errlog=httrack.log;
  1520.       if (httrack.log==NULL) {
  1521.         char s[HTS_CDLMAXSIZE];
  1522.         sprintf(s,"Unable to create log file %s",fconcat(httrack.path_log,"hts-log.txt"));
  1523.         HTS_PANIC_PRINTF(s);
  1524.         return -1;
  1525.       } else if (httrack.errlog==NULL) {
  1526.         char s[HTS_CDLMAXSIZE];
  1527.         sprintf(s,"Unable to create log file %s",fconcat(httrack.path_log,"hts-err.txt"));
  1528.         HTS_PANIC_PRINTF(s);
  1529.         return -1;
  1530.       }
  1531.  
  1532.     } else {
  1533.       httrack.log=NULL;
  1534.       httrack.errlog=NULL;
  1535.     }
  1536.     
  1537.     // un petit lock-file pour indiquer un miroir en cours, ainsi qu'un Θventuel fichier log
  1538.     {
  1539.       FILE* fp=NULL;
  1540.       //int n=0;
  1541.       char t[256];
  1542.       time_local_rfc822(t);    // faut bien que ca serve quelque part l'heure RFC1945 arf'
  1543.       
  1544.       /* readme for information purpose */
  1545.       {
  1546.         FILE* fp=fopen(fconcat(httrack.path_log,"hts-cache/readme.txt"),"wb");
  1547.         if (fp) {
  1548.           fprintf(fp,"What's in this folder?"LF);
  1549.           fprintf(fp,""LF);
  1550.           fprintf(fp,"This folder (hts-cache) has been generated by WinHTTrack "HTTRACK_VERSION""LF);
  1551.           fprintf(fp,"and is used for updating this website."LF);
  1552.           fprintf(fp,"(The HTML website structure is stored here to allow fast updates)"LF""LF);
  1553.           fprintf(fp,"DO NOT delete this folder unless you do not want to update the mirror in the future!!"LF);
  1554.           fprintf(fp,"(you can safely delete old.dat, old.ndx and old.lst files, however)"LF);
  1555.           fprintf(fp,""LF);
  1556.           fprintf(fp,HTS_LOG_SECURITY_WARNING);
  1557.           fclose(fp);
  1558.         }
  1559.       }
  1560.  
  1561.       sprintf(n_lock,fconcat(httrack.path_log,"hts-in_progress.lock"));
  1562.       //sprintf(n_lock,fconcat(httrack.path_log,"hts-in_progress.lock"),n);
  1563.       /*do {
  1564.         if (!n)
  1565.           sprintf(n_lock,fconcat(httrack.path_log,"hts-in_progress.lock"),n);
  1566.         else
  1567.           sprintf(n_lock,fconcat(httrack.path_log,"hts-in_progress%d.lock"),n);
  1568.         n++;
  1569.       } while((fexist(n_lock)) && httrack.quiet);      
  1570.       if (fexist(n_lock)) {
  1571.         if (!recuperer) {
  1572.           remove(n_lock);
  1573.         }
  1574.       }*/
  1575.  
  1576.       // vΘrifier existence de la structure
  1577.       structcheck(httrack.path_html);
  1578.       structcheck(httrack.path_log);
  1579.      
  1580.       // reprise/update
  1581.       if (httrack.cache) {
  1582.         FILE* fp;
  1583.         int i;
  1584. #if HTS_WIN
  1585.         mkdir(fconcat(httrack.path_log,"hts-cache"));
  1586. #else
  1587.         mkdir(fconcat(httrack.path_log,"hts-cache"),HTS_PROTECT_FOLDER);
  1588. #endif
  1589.         fp=fopen(fconcat(httrack.path_log,"hts-cache/doit.log"),"wb");
  1590.         if (fp) {
  1591.           for(i=0+1;i<argc;i++) {
  1592.             if ( ((strchr(argv[i],' ')!=NULL) || (strchr(argv[i],'"')!=NULL) || (strchr(argv[i],'\\')!=NULL)) && (argv[i][0]!='"')  ) {
  1593.               int j;
  1594.               fprintf(fp,"\"");
  1595.               for(j=0;j<(int) strlen(argv[i]);j++) {
  1596.                 if (argv[i][j]==34)
  1597.                   fprintf(fp,"\\\"");
  1598.                 else if (argv[i][j]=='\\')
  1599.                   fprintf(fp,"\\\\");
  1600.                 else
  1601.                   fprintf(fp,"%c",argv[i][j]);
  1602.               }
  1603.               fprintf(fp,"\"");
  1604.             } else if (strnotempty(argv[i])==0) {   // ""
  1605.               fprintf(fp,"\"\"");
  1606.             } else {   // non critique
  1607.               fprintf(fp,"%s",argv[i]);
  1608.             }
  1609.             if (i<argc-1)
  1610.               fprintf(fp," ");
  1611.           }
  1612.           fprintf(fp,LF);
  1613.           fprintf(fp,"File generated automatically on %s, do NOT edit"LF,t);
  1614.           fprintf(fp,LF);
  1615.           fprintf(fp,"To update a mirror, just launch httrack without any parameters"LF);
  1616.           fprintf(fp,"The existing cache will be used (and modified)"LF);
  1617.           fprintf(fp,"To have other options, retype all parameters and launch HTTrack"LF);
  1618.           fprintf(fp,"To continue an interrupted mirror, just launch httrack without any parameters"LF);
  1619.           fprintf(fp,LF);
  1620.           fclose(fp); fp=NULL;
  1621.         //} else if (httrack.debug>1) {
  1622.         //  printf("! FileOpen error, \"%s\"\n",strerror(errno));
  1623.         }
  1624.       }
  1625.       
  1626.       // petit message dans le lock
  1627.       if ( (fp=fopen(n_lock,"wb"))!=NULL) {
  1628.         int i;
  1629.         fprintf(fp,"Mirror in progress since %s .. please wait!"LF,t);
  1630.         for(i=0;i<argc;i++) {
  1631.           if (strchr(argv[i],' ')==NULL)
  1632.             fprintf(fp,"%s ",argv[i]);
  1633.           else    // entre ""
  1634.             fprintf(fp,"\"%s\" ",argv[i]);
  1635.         }
  1636.         fprintf(fp,LF);
  1637.         fclose(fp); fp=NULL;
  1638.       }
  1639.       
  1640.       // fichier log        
  1641.       if (httrack.log)     {
  1642.         int i;
  1643.         fprintf(httrack.log,"HTTrack"HTTRACK_VERSION" launched on %s at %s"LF,t,url);
  1644.         fprintf(httrack.log,"(");
  1645.         for(i=0;i<argc;i++) {
  1646.           if ((strchr(argv[i],' ')==NULL) || (strchr(argv[i],'\"')))
  1647.             fprintf(httrack.log,"%s ",argv[i]);
  1648.           else    // entre "" (si espace(s) et pas dΘja de ")
  1649.             fprintf(httrack.log,"\"%s\" ",argv[i]);
  1650.         }
  1651.         fprintf(httrack.log,")"LF);
  1652.         fprintf(httrack.log,LF);
  1653.         fprintf(httrack.log,"Information, Warnings and Errors reported for this mirror:"LF);
  1654.         fprintf(httrack.log,HTS_LOG_SECURITY_WARNING );
  1655.         fprintf(httrack.log,LF);
  1656.       }
  1657.  
  1658.       if (httrack_logmode)     {
  1659.         printf("Mirror launched on %s by HTTrack Website Copier/"HTTRACK_VERSION" "HTTRACK_AFF_AUTHORS""LF,t);
  1660.         if (httrack.wizard==0) {
  1661.           printf("mirroring %s with %d levels, %d sockets,t=%d,s=%d,logm=%d,lnk=%d,mdg=%d\n",url,httrack.depth,httrack.maxsoc,httrack.travel,httrack.seeker,httrack_logmode,httrack.urlmode,httrack.getmode);
  1662.         } else {    // the magic wizard
  1663.           printf("mirroring %s with the wizard help..\n",url);
  1664.         }
  1665.       }
  1666.     }
  1667.     
  1668.     io_flush;
  1669.  
  1670.   /* Info for wrappers */
  1671.   if ( (httrack.debug>0) && (httrack.log!=NULL) ) {
  1672.     fspc(httrack.log,"info"); fprintf(httrack.log,"engine: init"LF);
  1673.   }
  1674. #if HTS_ANALYSTE
  1675.   hts_htmlcheck_init();
  1676. #endif
  1677.  
  1678.   // dΘtourner SIGHUP etc.
  1679. #if HTS_WIN
  1680.   signal( SIGINT  , sig_ask    );   // ^C
  1681.   signal( SIGTERM , sig_finish );   // kill <process>
  1682. #else
  1683.   signal( SIGHUP  , sig_back   );   // close window
  1684.   signal( SIGTSTP , sig_back   );   // ^Z
  1685.   signal( SIGTERM , sig_finish );   // kill <process>
  1686.   signal( SIGINT  , sig_ask    );   // ^C
  1687. /*
  1688. deprecated - see SIGCHLD
  1689. #ifndef HTS_DO_NOT_SIGCLD
  1690.   signal( SIGCLD  , sig_ignore );   // child change status
  1691. #endif
  1692. */
  1693.   signal( SIGCHLD , sig_ignore );   // child change status
  1694. #endif
  1695. #if DEBUG_STEPS
  1696.   printf("Launching the mirror\n");
  1697. #endif
  1698.   
  1699.  
  1700.     // Lancement du miroir
  1701.     // ------------------------------------------------------------
  1702.     if (httpmirror(url,httrack)==0) {
  1703.       printf("Error during operation (see log file), site has not been successfully mirrored\n");
  1704.     } else {
  1705.       if  (httrack.shell) {
  1706.         HTT_REQUEST_START;
  1707.         HT_PRINT("TRANSFER DONE"LF);
  1708.         HTT_REQUEST_END
  1709.       } else {
  1710.         printf("Done.\n");
  1711.       }
  1712.     }
  1713.     // ------------------------------------------------------------
  1714.  
  1715.     //
  1716.     // Build top index
  1717.     if (httrack.dir_topindex) {
  1718.       char rpath[1024*2];
  1719.       char* a;
  1720.       strcpy(rpath,httrack.path_html);
  1721.       if (rpath[0]) {
  1722.         if (rpath[strlen(rpath)-1]=='/')
  1723.           rpath[strlen(rpath)-1]='\0';
  1724.       }
  1725.       a=strrchr(rpath,'/');
  1726.       if (a) {
  1727.         *a='\0';
  1728.         hts_buildtopindex(rpath,httrack.path_bin);
  1729.         if (httrack.log) {
  1730.           fspc(httrack.log,"info"); fprintf(httrack.log,"Top index rebuilt (done)"LF);
  1731.         }
  1732.       }
  1733.     }
  1734.  
  1735.     if (exit_xh ==1) {
  1736.       if (httrack.log) {
  1737.         fprintf(httrack.log,"* * MIRROR ABORTED! * *\nThe current temporary cache is required for any update operation and only contains data downloaded during the present aborted session.\nThe former cache might contain more complete information; if you do not want to lose that information, you have to restore it and delete the current cache.\nThis can easily be done here by erasing the hts-cache/new.* files]\n");
  1738.       }
  1739.     }
  1740.  
  1741.   /* Info for wrappers */
  1742.   if ( (httrack.debug>0) && (httrack.log!=NULL) ) {
  1743.     fspc(httrack.log,"info"); fprintf(httrack.log,"engine: free"LF);
  1744.   }
  1745. #if HTS_ANALYSTE
  1746.   hts_htmlcheck_uninit();
  1747. #endif
  1748.     
  1749.     if (httrack_logmode==1) {
  1750.       if (httrack.errlog == httrack.log) httrack.errlog=NULL;
  1751.       if (httrack.log) { fclose(httrack.log); httrack.log=NULL; }
  1752.       if (httrack.errlog) { fclose(httrack.errlog); httrack.errlog=NULL; }
  1753.     }  
  1754.     
  1755.     // DΘbuggage des en tΩtes
  1756.     if (_DEBUG_HEAD) {
  1757.       if (ioinfo) {
  1758.         fclose(ioinfo);
  1759.       }
  1760.     }
  1761.     
  1762.     // supprimer lock
  1763.     remove(n_lock);
  1764.   }
  1765.   
  1766.   if (x_argvblk)
  1767.     freet(x_argvblk);
  1768.  
  1769. #if HTS_WIN
  1770. #if HTS_ANALYSTE!=2
  1771. //  WSACleanup();    // ** non en cas de thread tjs prΘsent!..
  1772. #endif
  1773. #endif
  1774. #if HTS_TRACE_MALLOC
  1775.   hts_freeall();
  1776. #endif
  1777.  
  1778.   printf("Thanks for using HTTrack!\n");
  1779.   io_flush;
  1780.   return 0;    // OK
  1781. }
  1782.  
  1783.  
  1784. // main() subroutines
  1785.  
  1786. // vΘrifier chemin path
  1787. int check_path(char* s,char* defaultname) {
  1788.   int i;
  1789.   int return_value=0;
  1790.  
  1791.   // Replace name: ~/mywebsites/# -> /home/foo/mywebsites/#
  1792.   expand_home(s);
  1793.   for(i=0;i<(int) strlen(s);i++)    // conversion \ -> /
  1794.     if (s[i]=='\\')
  1795.       s[i]='/';
  1796.   
  1797.   // remove ending /
  1798.   if (strnotempty(s))
  1799.   if (s[strlen(s)-1]=='/')
  1800.     s[strlen(s)-1]='\0';
  1801.  
  1802.    // Replace name: /home/foo/mywebsites/# -> /home/foo/mywebsites/wonderfulsite
  1803.   if (strnotempty(s)) {
  1804.     if (s[(i=strlen(s))-1]=='#') {
  1805.       if (strnotempty((defaultname?defaultname:""))) {
  1806.         char tempo[HTS_URLMAXSIZE*2];
  1807.         char* a=strchr(defaultname,'#');      // we never know..
  1808.         if (a) *a='\0';
  1809.         tempo[0]='\0';
  1810.         strncat(tempo,s,i-1);
  1811.         strcat(tempo,defaultname);
  1812.         strcpy(s,tempo);
  1813.       } else
  1814.         s[0]='\0';            // Clear path (no name/default url given)
  1815.       return_value=1;     // expanded
  1816.     }
  1817.   }
  1818.  
  1819.   // ending /
  1820.   if (strnotempty(s))
  1821.   if (s[strlen(s)-1]!='/')    // ajouter slash α la fin
  1822.     strcat(s,"/");
  1823.  
  1824.   return return_value;
  1825. }
  1826.  
  1827. // dΘtermine si l'argument est une option
  1828. int cmdl_opt(char* s) {
  1829.   if (s[0]=='-') {  // c'est peut Ωtre une option
  1830.     if (strchr(s,'.')!=NULL)
  1831.       return 0;    // sans doute un -www.truc.fr (note: -www n'est pas compris)
  1832.     else if (strchr(s,'/')!=NULL)
  1833.       return 0;    // idem, -*cgi-bin/
  1834.     else if (strchr(s,'*')!=NULL)
  1835.       return 0;    // joker, idem
  1836.     else
  1837.       return 1;
  1838.   } else return 0;
  1839. }
  1840.  
  1841.